//
//  HQNaviManager.m
//  o_amap
//
//  Created by Q神 on 2021/4/6.
//

#import "HQNaviManager.h"
/// 导航
#import <AMapNaviKit/AMapNaviKit.h>
#import "DriveRouteDataModel.h"

#import "HQMapTools.h"
#import "MJExtension.h"
#import "HQNaviCalculateResultModel.h"
#import "HQNaviDriveRouteOptionsModel.h"
#import "HQNaviStartNaviOptionsModel.h"

@interface HQNaviManager() <AMapNaviCompositeManagerDelegate, AMapNaviDriveManagerDelegate>

@property (nonatomic, strong) FlutterResult flutterResult;

@property (nonatomic, strong) AMapNaviCompositeManager *naviCompositeManager;
@property (nonatomic, strong) AMapNaviDriveManager *naviDriveManager;

@property (nonatomic, strong) HQMapTools * mapTools;

@end

@implementation HQNaviManager

+ (instancetype)shareInstance {
    static dispatch_once_t onceToken;
    static HQNaviManager * manager = nil;
    dispatch_once(&onceToken, ^{
        manager = [[HQNaviManager alloc] init];
    });
    return manager;
}

#pragma mark -- 插件方法

- (void)naviWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar withMapPlugin:(NSObject<FlutterPlugin> * _Nonnull)mapPlugin {

    FlutterMethodChannel *locationChannel = [FlutterMethodChannel methodChannelWithName:@"com.p595263720.zit/nav" binaryMessenger:[registrar messenger]];
    [registrar addMethodCallDelegate:mapPlugin channel:locationChannel];
}

- (void)naviMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {

    self.flutterResult = result;
    
    if([@"calculateDriveRoute" isEqualToString:call.method]) {
        /// 经纬度算路
        [self calculateDriveRoute:call];
        
    } else if([@"startNav" isEqualToString:call.method]) {
        /// 导航
        [self startNav:call];

    }
}

#pragma mark -- 导航回调

- (void)compositeManagerOnCalculateRouteSuccess:(AMapNaviCompositeManager *)compositeManager {
}

/// 当路线规划成功时，会触发-driveManager:onCalculateRouteSuccessWithType: 回调，在该回调函数中，可以进行规划路线的显示，也可以直接开始导航。
- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type {
    
    NSLog(@"onCalculateRouteSuccess");
    /// 显示路径或开始导航
    [self buildRouteDataSource];
}

#pragma mark -- 事件处理

- (void)calculateDriveRoute:(FlutterMethodCall *)call {
    if (call.arguments) {
        HQNaviDriveRouteOptionsModel *model = [HQNaviDriveRouteOptionsModel mj_objectWithKeyValues:call.arguments];
        [model calculateDriveRouteWithNaviDriveManager:self.naviDriveManager];
    }
}

- (void)startNav:(FlutterMethodCall *)call {
    if (call.arguments) {
        HQNaviStartNaviOptionsModel *model = [HQNaviStartNaviOptionsModel mj_objectWithKeyValues:call.arguments];
        [model startNavWithNaviCompositeManager:self.naviCompositeManager];
        self.flutterResult(NULL);
    }
}

- (void)showMultiColorNaviRoutes {
    if ([self.naviDriveManager.naviRoutes count] <= 0) {
        return;
    }
    
    /// 将路径显示到地图上
    for (NSNumber *aRouteID in [self.naviDriveManager.naviRoutes allKeys]) {
        AMapNaviRoute *aRoute = [[self.naviDriveManager naviRoutes] objectForKey:aRouteID];
        int count = (int)[[aRoute routeCoordinates] count];
        
        /// 添加路径Polyline
        CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(count * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < count; i++) {
            AMapNaviPoint *coordinate = [[aRoute routeCoordinates] objectAtIndex:i];
            coords[i].latitude = [coordinate latitude];
            coords[i].longitude = [coordinate longitude];
        }
        
        NSMutableArray<UIImage *> *textureImagesArrayNormal = [NSMutableArray new];
        NSMutableArray<UIImage *> *textureImagesArraySelected = [NSMutableArray new];
        
        /// 添加路况图片
        for (AMapNaviTrafficStatus *status in aRoute.routeTrafficStatuses) {
//            UIImage *img = [self defaultTextureImageForRouteStatus:status.status isSelected:NO];
//            UIImage *selImg = [self defaultTextureImageForRouteStatus:status.status isSelected:YES];
//            if (img && selImg) {
//                [textureImagesArrayNormal addObject:img];
//                [textureImagesArraySelected addObject:selImg];
//            }
        }
        
//        MultiDriveRoutePolyline *mulPolyline = [MultiDriveRoutePolyline polylineWithCoordinates:coords count:count drawStyleIndexes:aRoute.drawStyleIndexes];
//        mulPolyline.polylineTextureImages = textureImagesArrayNormal;
//        mulPolyline.polylineTextureImagesSeleted = textureImagesArraySelected;
//        mulPolyline.routeID = aRouteID.integerValue;
//
//        [self.mapView addOverlay:mulPolyline];
//        free(coords);
//
//        /// 更新CollectonView的信息
//        RouteCollectionViewInfo *info = [[RouteCollectionViewInfo alloc] init];
//        info.routeID = [aRouteID integerValue];
//        info.title = [NSString stringWithFormat:@"路径ID:%ld | 路径计算策略:%ld (点击展示路线详情)", (long)[aRouteID integerValue], (long)[self.preferenceView strategyWithIsMultiple:self.isMultipleRoutePlan]];
//        info.subtitle = [NSString stringWithFormat:@"长度:%ld米 | 预估时间:%ld秒 | 分段数:%ld", (long)aRoute.routeLength, (long)aRoute.routeTime, (long)aRoute.routeSegments.count];
//
//        [self.routeIndicatorInfoArray addObject:info];
    }
    
}

- (void)buildRouteDataSource {
    
    NSMutableArray *routeDataArray = @[].mutableCopy;
//    for (NSNumber *routeID in [AMapNaviDriveManager sharedInstance].naviRoutes) {
//        /// 获取每条路线
//        AMapNaviRoute *route = [[AMapNaviDriveManager sharedInstance].naviRoutes objectForKey:routeID];
//        /// 获取路线详情数据模型
//        NSArray *aRouteData = [self buildExtendGroupSegmentForRoute:route wayPointNames:nil];
//        if (aRouteData.count) {
//            NSArray *dictArray = [RouteGroupSegmentModel mj_keyValuesArrayWithObjectArray:aRouteData];
//            [routeDataArray addObject:dictArray];
//        }
//    }
    
    for (NSNumber *routeID in [AMapNaviDriveManager sharedInstance].naviRoutes) {
        /// 获取每条路线
        AMapNaviRoute *route = [[AMapNaviDriveManager sharedInstance].naviRoutes objectForKey:routeID];
        HQNaviCalculateResultModel *resultModel = [HQNaviCalculateResultModel initWithAMapNaviRoute:route];
        [routeDataArray addObject:resultModel];
    }
    NSMutableArray *dictArray = [HQNaviCalculateResultModel mj_keyValuesArrayWithObjectArray:routeDataArray.copy];
    NSString *jsonString = [self.mapTools hq_jsonStringPrettyPrintedFormatForDictionary:@{@"result":dictArray}];
    self.flutterResult(jsonString);
}

- (NSArray <RouteGroupSegmentModel *> *)buildExtendGroupSegmentForRoute:(AMapNaviRoute *)aRoute wayPointNames:(NSArray <NSString *>*)wayPointNames {
    if (aRoute == nil || [[aRoute routeGroupSegments] count] <= 0 || aRoute.routeSegmentCount <= 0) {
        return nil;
    }
    
    int wapPointIndex = 0;
    
    NSMutableArray <RouteGroupSegmentModel *> *result = [[NSMutableArray alloc] init];
    for (int i = 0; i < aRoute.routeGroupSegments.count; i++) {
        @autoreleasepool {
            AMapNaviGroupSegment *aGroupSegment = [aRoute.routeGroupSegments objectAtIndex:i];
            RouteGroupSegmentModel *aExtendGroupSegment = [[RouteGroupSegmentModel alloc] init];
            
            int trafficLightCount = 0;
            NSMutableArray <RouteSegmentDetailModel *> *extendSegments = [[NSMutableArray alloc] init];
            
            for (NSInteger j = aGroupSegment.startSegmentID; j < aGroupSegment.startSegmentID+aGroupSegment.segmentCount; j++)  {
                AMapNaviSegment *aSegment = [aRoute.routeSegments objectAtIndex:j];
                RouteSegmentDetailModel *aExtendSegment = [[RouteSegmentDetailModel alloc] init];
                
                [aExtendSegment setIconType:aSegment.iconType];
                [aExtendSegment setIsArriveWayPoint:aSegment.isArriveWayPoint];
                
                /// detailedDescription
                if (j+1 >= aRoute.routeSegmentCount) {
                    NSString *detailString = [NSString stringWithFormat:@"行驶%@%@到达终点",
                                              [self normalizedRemainDistance:aSegment.length],
                                              [self descriptionForIconType:aSegment.iconType]];
                    [aExtendSegment setDetailedDescription:detailString];
                    
                    /// modify iconType
                    [aExtendSegment setIconType:AMapNaviIconTypeStraight];
                } else {
                    if (aSegment.isArriveWayPoint) {
                        if (wapPointIndex < [wayPointNames count]) {
                            [aExtendSegment setDetailedDescription:[NSString stringWithFormat:@"到达途经点 %@", [wayPointNames objectAtIndex:wapPointIndex]]];
                            ++wapPointIndex;
                        } else {
                            [aExtendSegment setDetailedDescription:@"到达途经点"];
                        }
                    } else {
                        AMapNaviSegment *nextSegment = [aRoute.routeSegments objectAtIndex:j+1];
                        
                        NSString *detailString = [NSString stringWithFormat:@"行驶%@%@进入%@",
                                                  [self normalizedRemainDistance:aSegment.length],
                                                  [self descriptionForIconType:aSegment.iconType],
                                                  [[[nextSegment links] firstObject] roadName]];
                        [aExtendSegment setDetailedDescription:detailString];
                    }
                }
                
                /// trafficLightCount
                trafficLightCount += aSegment.trafficLightCount;
                
                [extendSegments addObject:aExtendSegment];
            }
            
            [aExtendGroupSegment setExtendSegments:extendSegments];
            [aExtendGroupSegment setGroupName:aGroupSegment.groupName];
            [aExtendGroupSegment setDistance:aGroupSegment.distance];
            [aExtendGroupSegment setTrafficLightCount:trafficLightCount];
            
            /// modify iconType
            [aExtendGroupSegment setIconType:[[aRoute.routeSegments objectAtIndex:aGroupSegment.startSegmentID] iconType]];
            if (aExtendGroupSegment.iconType == AMapNaviIconTypeArrivedWayPoint || aExtendGroupSegment.iconType == AMapNaviIconTypeArrivedDestination)
            {
                [aExtendGroupSegment setIconType:AMapNaviIconTypeStraight];
            }
            
            [result addObject:aExtendGroupSegment];
        }/// autoreleasepool
    }
    
    return result;
}

- (NSString *)descriptionForIconType:(AMapNaviIconType)iconType {
    static NSDictionary *mappings = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        mappings = @{@(AMapNaviIconTypeNone): @"",
                     @(AMapNaviIconTypeDefault): @"",
                     @(AMapNaviIconTypeLeft): @"左转",
                     @(AMapNaviIconTypeRight): @"右转",
                     @(AMapNaviIconTypeLeftFront): @"向左前方转",
                     @(AMapNaviIconTypeRightFront): @"向右前方转",
                     @(AMapNaviIconTypeLeftBack): @"向左后转",
                     @(AMapNaviIconTypeRightBack): @"向右后转",
                     @(AMapNaviIconTypeLeftAndAround): @"左转掉头",
                     @(AMapNaviIconTypeStraight): @"直行",
                     @(AMapNaviIconTypeArrivedWayPoint) : @"",
                     @(AMapNaviIconTypeEnterRoundabout) : @"进入环岛",
                     @(AMapNaviIconTypeOutRoundabout): @"驶出环岛",
                     @(AMapNaviIconTypeArrivedServiceArea): @"",
                     @(AMapNaviIconTypeArrivedTollGate): @"",
                     @(AMapNaviIconTypeArrivedDestination): @"直行",
                     @(AMapNaviIconTypeArrivedTunnel): @"",
                     @(AMapNaviIconTypeCrosswalk): @"",
                     @(AMapNaviIconTypeFlyover): @"",
                     @(AMapNaviIconTypeUnderpass): @""
                     };
    });
    
    NSString *description = [mappings objectForKey:@(iconType)];
    if (description == nil) {
        description = [mappings objectForKey:@(AMapNaviIconTypeNone)];
    }
    
    return description;
}

- (nullable NSString *)normalizedRemainDistance:(NSInteger)remainDistance {
    if (remainDistance < 0) {
        return nil;
    }
    
    if (remainDistance >= 1000) {
        NSString *distStr = [NSString stringWithFormat:@"%.1f公里",remainDistance/1000.0];
        return distStr;
    } else {
        return [NSString stringWithFormat:@"%ld米", (long)remainDistance];
    }
}

#pragma mark -- 懒加载

- (AMapNaviCompositeManager *)naviCompositeManager {
    if (!_naviCompositeManager) {
        /// 初始化
        _naviCompositeManager = [[AMapNaviCompositeManager alloc] init];
        /// 如果需要使用AMapNaviCompositeManagerDelegate的相关回调（如自定义语音、获取实时位置等），需要设置delegate
        _naviCompositeManager.delegate = self;
    }
    return _naviCompositeManager;
}

- (AMapNaviDriveManager *)naviDriveManager {
    if (!_naviDriveManager) {
        _naviDriveManager = [AMapNaviDriveManager sharedInstance];
        _naviDriveManager.delegate = self;
    }
    return _naviDriveManager;
}

- (HQMapTools *)mapTools {
    if (!_mapTools) {
        _mapTools = [HQMapTools shareInstance];
    }
    return _mapTools;
}

@end
